package com.swagger.demo.util;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * creat by
 *
 * @author heyang
 * @date 2020/9/10 15:46
 */
public class BeanUtilsEx extends BeanUtils {

    // 描述要映射的对象忽略一些属性
    public static Map<String, Object> describe(Object source, String... ignoreProperties) {
        return describe(source, false, ignoreProperties);
    }

    // 描述要映射的对象忽略空值和一些属性
    public static Map<String, Object> describe(Object source, boolean ignoreNullValue,
                                               String... ignoreProperties) {
        Assert.notNull(source, "source must not be null");
        Map<String, Object> target = new HashMap<String, Object>();
        Class<?> clazz = source.getClass();
        PropertyDescriptor[] pds = getPropertyDescriptors(clazz);
        List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties)
                : null;

        for (PropertyDescriptor pd : pds) {
            if (pd.getReadMethod() != null && !pd.getName().equals("class")
                    && (ignoreProperties == null || (!ignoreList.contains(pd.getName())))) {
                try {
                    Method readMethod = pd.getReadMethod();
                    if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                        readMethod.setAccessible(true);
                    }
                    Object value = readMethod.invoke(source);
                    if (ignoreNullValue && null == value) {
                        continue;
                    }
                    target.put(pd.getName(), value);
                } catch (Throwable ex) {
                    throw new FatalBeanException(
                            "Could not copy properties from source to target:(" + pd.getName() + ")",
                            ex);
                }
            }
        }
        return target;
    }

}
